[AGC003D]Anticube

2020-02-08
Atcoder

题意

在$n$个数中选出$Max$个数,使得它们任意两个相乘不为立方数

求$Max$

题解

在本题中,$a_i=p_1^{k_1}\cdots p_x^{k_x}$和$a_i=p_1^{k_1\space mod\space 3}\cdots p_x^{k_x\space mod\space 3}$等价

令$b_i=\frac{p_1^{3}\cdots p_x^3}{a_i}$

发现冲突一定是互相的,当有冲突,取较多的,本身是立方数的分开考虑

调试记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <cstdio>
#include <algorithm>
#include <map>
#include <vector>
#include <cmath>
#define LL long long
const int maxn = 1e5 + 5;
const int maxP = 1e4;
using namespace std;
LL a[maxn], b[maxn]; int n;
map <LL, int> m;
vector <LL> p;
bool f[maxn];
void install(){
for (int i = 2; i <= maxP; i++){
if (!f[i]) p.push_back(i);
for (int j = 0; j < p.size() && i * p[j] <= maxP; j++){
f[i * p[j]] = 1;
if (i % p[j] == 0) continue;
}
}
}
LL split(LL &x){
LL res1 = 1, res2 = 1;
for (int i = 0; i < p.size(); i++){
if (x % p[i] != 0) continue;
int cnt = 0;
while (x % p[i] == 0) ++cnt, x /= p[i];
cnt %= 3;
if (cnt == 2) res1 = res1 * p[i] * p[i], res2 = res2 * p[i];
else if (cnt == 1) res1 = res1 * p[i], res2 = res2 * p[i] * p[i];
}
if (x != 1){
if ((LL)sqrt(x) * (LL)sqrt(x) == x) res1 *= x, res2 *= (LL)sqrt(x);
else res1 *= x, res2 *= x * x;
}
x = res1;
return res2;
}
int main(){
scanf("%d", &n); install();
// for (int i = 0; i < 20; i++) printf("%d\n", p[i]);
for (int i = 1; i <= n; i++){
scanf("%lld", a + i);
b[i] = split(a[i]);
m[a[i]]++;
} int ans = (m[1] != 0); m[1] = 0;
for (int i = 1; i <= n; i++){
if (m[b[i]] != 0) ans += max(m[a[i]], m[b[i]]), m[a[i]] = 0, m[b[i]] = 0;
else ans += m[a[i]], m[a[i]] = 0;
} printf("%d\n", ans);
return 0;
}